package com.bbz.core.lambda;

import groovy.lang.IntRange;

import javax.swing.text.html.Option;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Optional;
import java.util.Timer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.util.stream.Collectors.joining;

/**
 * @author binbin.zhang
 */
public class LambdaTest {
    public static void main(String args[]) {

        String[] planets = new String[]{"Mercury", "Binbin", "Venus", "Mars"};

        System.out.println(Arrays.toString(planets));
        //排序（Arrays.sort使用的是快速排序法）
        Arrays.sort(planets);
        /**
         * java8 排序
         * Comparator.naturalOrder方法。这是Comparator接口的一个全新的静态方法，它返回一个Comparator对象，并按自然序列对其中的元素进行排序（即标准的字母数字方式排序）。
         */
        List<Integer> numbers = Arrays.asList(3, 5, 1, 2, 6);
        numbers.sort(Comparator.naturalOrder());

        List<String> features = Arrays.asList("bb", "Lambdas", "Default Method", "Stream API", "Date and Time API");

        System.out.println("***********************************************");
        //*********************lambda表达式 使用Predicate 过滤
        List<String> languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
        //按照开头是J的过滤
        System.out.println("Languages which starts with J :");
        filter(languages, (str) -> str.startsWith("J"));
        //按照结尾是a的过滤
        System.out.println("Languages which ends with a ");
        filter(languages, (str) -> str.endsWith("a"));
        //全部输出
        System.out.println("Print all languages :");
        filter(languages, (str) -> true);
        //全部不输出
        System.out.println("Print no language : ");
        filter(languages, (str) -> false);
        //过滤长度大于4的
        System.out.println("Print language whose length greater than 4:");
        filter(languages, (str) -> str.length() > 4);

        //*********************lambda表达式  例如要找到所有以J开始，长度为四个字母的名字，你可以合并两个Predicate并传入
        Predicate<String> startsWithJ = (n) -> n.startsWith("J");
        Predicate<String> fourLetterLong = (n) -> n.length() == 4;
        //顺序执行
        languages.stream()
                .filter(startsWithJ.and(fourLetterLong))
                .forEach((n) -> System.out.println("nName, which starts with 'J' and four letter long is : " + n));

        //parallelStream 并行流处理
        languages.parallelStream().filter(startsWithJ.and(fourLetterLong))
                .forEach((n) -> System.out.println("parallelStream:nName, which starts with 'J' and four letter long is : " + n));

        // 不使用lambda表达式为每个订单加上12%的税
        List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);

        //*********************lambda表达式 使用lambda表达式 为每个订单加上12%的税
        costBeforeTax.stream().map((cost) -> cost + .12 * cost).forEach(System.out::println);


        //*********************lambda表达式  为每个订单加上12%的税，然后计算总和
        List<Double> costBeforeTax1 = Arrays.asList(100.00, 200.00, 300.00, 400.00, 500.00, 600.00);
        double bill = costBeforeTax1.stream().map((cost) -> cost + .12 * cost).reduce((sum, cost) -> sum + cost).get();
        System.out.println("Total : " + bill);


        //*********************lambda表达式，按照字符串长度排序
        Arrays.sort(planets, (first, second) -> first.length() - second.length());


        //*********************lambda方式 创建线程：
        new Thread(() -> System.out.println("In Java8, Lambda expression rocks !")).start();


        //*********************lambda方式 遍历集合：
        features.forEach(n -> System.out.println(n));
        // 使用Java 8的方法引用更方便，方法引用由::双冒号操作符标示，
        features.forEach(System.out::println);


        //*********************lambda方式 创建一个字符串列表，每个字符串长度大于2
        List<String> filtered = features.stream().filter(x -> x.length() > 2).collect(Collectors.toList());
        System.out.printf("Original List : %s, filtered list : %s %n", features, filtered);
        String ss= features.stream().collect(joining(","));
        System.out.println("*************Collectors.joining:"+ ss);

        //*********************lambda方式 将字符串换成大写并用逗号链接起来
        List<String> G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.", "Canada");
        String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(joining(", "));
        System.out.println(G7Countries);

        //*********************lambda方式 用所有不同的数字创建一个正方形列表
        List<Integer> numbers1 = Arrays.asList(9, 10, 3, 4, 7, 3, 4);
        List<Integer> distinct = numbers1.stream().map(i -> i * i).distinct().collect(Collectors.toList());
        System.out.printf("Original List : %s,  Square Without duplicates : %s %n", numbers1, distinct);
        boolean a = numbers1.stream().anyMatch(t -> 10 == t);
        System.out.println("anyMatch***************" + a);

        //*********************lambda方式获取数字的个数、最小值、最大值、总和以及平均值
        List<Integer> primes = Arrays.asList(2, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
        //IntSummaryStatistics用于收集统计信息的状态对象，如count、min、max、sum和avg
        IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
        System.out.println("Highest prime number in List : " + stats.getMax());
        System.out.println("Lowest prime number in List : " + stats.getMin());
        System.out.println("Sum of all prime numbers : " + stats.getSum());
        System.out.println("Average of all prime numbers : " + stats.getAverage());

        //将顺序流转化为并行流
        System.out.println("***********"+parallelSum(10));
        final String SENTENCE =" Nel mezzo del cammin di nostra vita " +"mi ritrovai in una selva oscura" +
                        " ché la dritta via era smarrita ";
        //流类型转换
        Stream<Character> stream=IntStream.range(0,SENTENCE.length()).mapToObj(SENTENCE::charAt);
        System.out.println("***********处理器数量"+Runtime.getRuntime().availableProcessors());

        //Java8 lambda 拼接字符串
        String aa=features.stream().collect(joining(", "));
        System.out.println("***********Java8 lambda 拼接字符串:"+aa);

        //顺序流和并行流find any 速度比较
        anyMath();

        IntStream.range(0,0).forEach(j-> System.out.println("xxxxx->"+j));

    }


    public static void filter(List<String> names, Predicate<String> condition) {
        String aa="";
        names.stream().filter((name) -> (condition.test(name))).forEach((name) -> {
            System.out.println(name + " ");
        });
    }


    public static long parallelSum(long n){
        return Stream.iterate(1L,i->i+1)
                .limit(n)
                .parallel()
                .reduce(0L,Long::sum);
    }


    public static void anyMath(){
        List<String> list=new ArrayList<>();
        IntStream.range(0,10000000).forEach(i->list.add(String.valueOf(i)));
        System.out.println(list);
        long start = System.nanoTime();
        list.stream().filter(c->c.equals(111)).findAny();
        long duration = (System.nanoTime() - start) / 1_000_000;
        System.out.println("stream in " + duration + " msecs");
        long start1 = System.nanoTime();
        list.parallelStream().filter(c->c.equals(111)).findAny();
        long duration1 = (System.nanoTime() - start1) / 1_000_000;
        System.out.println("parallelStream in " + duration1 + " msecs");
    }
}
